package com.wlanauth.web.core.file;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.log4j.Logger;

import com.wlanauth.web.core.JsonResult;
/**
 * 文件上传
 * @author zz
 * @date 2012-5-24
 * @email charles.zz.life@gmail.com
 */
public class FileUploadAction extends com.wlanauth.web.core.BaseActionSupport {
	private static final long serialVersionUID = 1L;
	
	private static Logger logger = Logger.getLogger(FileUploadAction.class);
	private File[] upload;
	private String[] uploadContentType;
	private String[] uploadFileName;

	private String savePath;//保存地址
	private String savePathRoot;//地址根
	
	private String allowType;//允许类型
	private long maxLength = 1024000;//最大大小
	
	private FileProcessor fileProcessor;//文件处理
	
	private boolean processSyncFlag ;// 同步处理标志
	
	private static ExecutorService executorService = Executors.newCachedThreadPool();
	
	public void setAllowType(String allowType) {
		this.allowType = allowType;
	}

	public long getMaxLength() {
		return maxLength;
	}

	public void setMaxLength(long maxLength) {
		this.maxLength = maxLength;
	}

	
	
	public File[] getUpload() {
		return upload;
	}

	public void setUpload(File[] upload) {
		this.upload = upload;
	}

	public String[] getUploadContentType() {
		return uploadContentType;
	}

	public void setUploadContentType(String[] uploadContentType) {
		this.uploadContentType = uploadContentType;
	}

	public String[] getUploadFileName() {
		return uploadFileName;
	}

	public void setUploadFileName(String[] uploadFileName) {
		this.uploadFileName = uploadFileName;
	}

	public String getSavePath() {
		return savePath;
	}

	public void setSavePath(String savePath) {
		this.savePath = savePath;
	}

	public String getAllowType() {
		return allowType;
	}

	private String getFileExten(String filename) {
		return  filename.substring(filename.lastIndexOf('.')).toLowerCase();
	}
	public File createSaveFile(String filename){
		Calendar c = Calendar.getInstance();
		String dir = getSavePath() + "/"+ new SimpleDateFormat("yyyyMM").format(c.getTime())+""+"/";
		//String sPath = this.request.getSession().getServletContext().getRealPath("/"+dir);
		String sPath = this.savePathRoot+"/"+dir;
		File f = new File(sPath);
		if (!f.exists())
			f.mkdirs();
		File file = newFile(sPath,filename,0);
		return file;
	}
	private File newFile(String dir,String filename,int index){
		File file = null;
		if(index<1){
			file = new File(dir,filename);
		} else {
			String filenameNoExt = filename.substring(0,filename.lastIndexOf("."));
			String regex = "_[0-9]+$";
			String newname = filenameNoExt.replaceAll(regex, "")+"_"+index+this.getFileExten(filename);
			file = new File(newname);
		}
		if(!file.exists()){
			return file;
		}
		if(index>1000){
			throw new RuntimeException("同名文件过多");
		}
		return newFile(dir,filename,index+1);
	}
	public String execute() {
		if(upload == null){
			this.jsonResult = new JsonResult(this,"未上传任何文件",false);
			return this.actionJsonResult();
		}
		List<File> files = new ArrayList<File>();
		for(int i=0;i<upload.length;i++){
			File file = upload[i];
			String fileExt = getFileExten(uploadFileName[i]);
			logger.debug("接收文件:"+file.getAbsolutePath());
			
			if (getAllowType().indexOf(fileExt) < 0) {
				this.jsonResult = new JsonResult(this,"请确认您上传的文件类型[允许上传:"+ this.getAllowType()+"]",false);
				return this.actionJsonResult();
			}
			if (file.length() > maxLength) {
				this.jsonResult = new JsonResult(this, "请确认您上传的文件大小[允许上传:"+ this.maxLength / 1000 + " KB]",false);
				return this.actionJsonResult();
			}
			File saveFile = this.createSaveFile(uploadFileName[i]);
			logger.debug("文件存放位置:"+saveFile.getAbsolutePath());
			try {
				
				FileInputStream in = new FileInputStream(file);
				
				FileOutputStream fos = new FileOutputStream(saveFile);
				byte[] buffer = new byte[1024];
				int len = 0;
				while ((len = in.read(buffer)) > 0) {
					fos.write(buffer, 0, len);
					fos.flush();
				}
				fos.close();
				in.close();
				
				files.add(saveFile);
				
			} catch (IOException e) {
				logger.error("文件上传IO读取出错:"+e.getMessage(),e);
				this.jsonResult = new JsonResult(this,"IO读取出错:"+e.getMessage(),false);
				return this.actionJsonResult();
			}
		}
		FileUploadResult result = null;
		if(this.fileProcessor!=null){
			if(!this.processSyncFlag){
				final List<File> tempFiles = files;
				executorService.execute(new Runnable(){

					public void run() {
						try {
							proccessFiles(tempFiles);
						} catch (Exception e){
							logger.error("异步处理文件异常",e);
						}
					}
				});
			} else {
				result = proccessFiles(files);
			}
			
		}
		this.jsonResult = new JsonResult(this,result,true);
		return this.actionJsonResult();
		
	}

	private FileUploadResult proccessFiles(List<File> files) {
		FileUploadResult result = null;
		try {
			FileProcessorContext ctx = new FileProcessorContext();
			ctx.setFiles(files);
			ctx.setAction(this);
			result = this.fileProcessor.process(ctx);
		} catch (FileProcessorException ex){
			logger.warn("文件处理异常:"+ex.getMessage(),ex);
			result = new FileUploadResult();
			result.setSuccess(false);
			result.setProcessResult("文件处理异常:"+ex.getMessage());
		}
		return result ;
		
	}
	public void setFileProcessor(FileProcessor fileProcessor) {
		this.fileProcessor = fileProcessor;
	}

	public void setProcessSyncFlag(boolean processSyncFlag) {
		this.processSyncFlag = processSyncFlag;
	}

	public String getSavePathRoot() {
		return savePathRoot;
	}

	public void setSavePathRoot(String savePathRoot) {
		this.savePathRoot = savePathRoot;
	}
	

}
